#pragma once
#include "../common/net.hpp"
#include "../common/message.hpp"
#include "requestor.hpp"

namespace MyRpc
{
    namespace client
    {
        class RpcCaller
        {
        public:
            using ptr = std::shared_ptr<RpcCaller>;
            using AsyncResponse = std::future<Json::Value>;
            using ResponseCallBack = std::function<void(const Json::Value&)>;
            RpcCaller(const Requestor::ptr& requestor)
                :_requestor(requestor)
            {}
            // 异步回调提供给用户的接口
            bool call(const BaseConnection::ptr& conn, const std::string& method, const Json::Value& param, AsyncResponse& result)
            {
                // 首先构造请求
                auto req = MessageFactory::create(MType::REQ_RPC);
                RpcRequest::ptr req_rpc = std::dynamic_pointer_cast<RpcRequest>(req);
                req_rpc->setId(UUID::uuid());
                req_rpc->setMType(MType::REQ_RPC);
                req_rpc->setMethod(method);
                req_rpc->setParameters(param);
                // 发送请求
                auto rsp_rpc = std::make_shared<std::promise<Json::Value>>();
                // 把结果设置到result中 外部可以直接获取
                result = rsp_rpc->get_future();
                Requestor::RequsetorCallBack cb = std::bind(&RpcCaller::callBack, this, rsp_rpc, std::placeholders::_1);
                bool flag = _requestor->send(conn, req, cb);
                // 用户需要的是请求返回的结果 也就是Json::Value的样子
                if(flag == false)
                {
                    LOG(DEBUGLEVEL, "异步回调失败");
                    return false;
                }
                return true;
            }
            // 同步回调
            bool call(const BaseConnection::ptr& conn, const std::string& method, const Json::Value& param, Json::Value& result)
            {
                // 首先构造请求
                auto req = MessageFactory::create(MType::REQ_RPC);
                RpcRequest::ptr req_rpc = std::dynamic_pointer_cast<RpcRequest>(req);
                req_rpc->setId(UUID::uuid());
                req_rpc->setMType(MType::REQ_RPC);
                req_rpc->setMethod(method);
                req_rpc->setParameters(param);
                BaseMessage::ptr rsp_rpc;
                // 发送请求
                bool flag = _requestor->send(conn, req, rsp_rpc);
                if(flag == false)
                {
                    LOG(DEBUGLEVEL, "同步回调失败");
                    return false;
                }
                // 等待接收应答
                auto rsp = std::dynamic_pointer_cast<RpcResponse>(rsp_rpc);
                if(rsp->rcode() != RCode::RCODE_OK)
                {
                    LOG(DEBUGLEVEL, "处理结果失败, %s", errReason(rsp->rcode()).c_str());
                    return false;
                }
                result = rsp->result();
                return true;
            }
            // 回调函数回调
            bool call(const BaseConnection::ptr& conn, const std::string& method, const Json::Value& param, const ResponseCallBack& cb)
            {
                // 首先构造请求
                auto req = MessageFactory::create(MType::REQ_RPC);
                RpcRequest::ptr req_rpc = std::dynamic_pointer_cast<RpcRequest>(req);
                req_rpc->setId(UUID::uuid());
                req_rpc->setMType(MType::REQ_RPC);
                req_rpc->setMethod(method);
                req_rpc->setParameters(param);

                Requestor::RequsetorCallBack callback = std::bind(&RpcCaller::callBack1, this, cb, std::placeholders::_1);
                bool flag = _requestor->send(conn, req, callback);
                // 用户需要的是请求返回的结果 也就是Json::Value的样子
                if(flag == false)
                {
                    LOG(DEBUGLEVEL, "回调函数rpc失败");
                    return false;
                }
                return true;
            }
        private:
            void callBack1(const ResponseCallBack& cb, const BaseMessage::ptr& rsp)
            {
                auto rsp_rpc = std::dynamic_pointer_cast<RpcResponse>(rsp);
                if(rsp_rpc->rcode() != RCode::RCODE_OK)
                {
                    LOG(DEBUGLEVEL, "处理结果失败, %s", errReason(rsp_rpc->rcode()).c_str());
                    return;
                }
                // 用回调函数对结果进行处理即可
                cb(rsp_rpc->result());
            }
            void callBack(std::shared_ptr<std::promise<Json::Value>>& result, const BaseMessage::ptr& rsp)
            {
                auto rsp_rpc = std::dynamic_pointer_cast<RpcResponse>(rsp);
                if(rsp_rpc->rcode() != RCode::RCODE_OK)
                {
                    LOG(DEBUGLEVEL, "处理结果失败, %s", errReason(rsp_rpc->rcode()).c_str());
                    return;
                }
                // 把结果放到promise对象中
                result->set_value(rsp_rpc->result());
            }
        private:
            Requestor::ptr _requestor;
        };
    }
}